#include "DefaultState.hpp"
#include "../Notification.hpp"
#include "../Util.hpp"
#include <TweenEngine/Tween.h>
#include <cpp3ds/System/I18n.hpp>
#include <cpp3ds/Window/Window.hpp>
#include <inttypes.h>
#ifndef EMULATION
#include <3ds.h>
#endif

namespace Clock {

DefaultState *g_defaultState = nullptr;

DefaultState::DefaultState(StateStack& stack, Context& context, StateCallback callback)
: State(stack, context, callback)
, m_mode(Mode_None)
, m_isTransitioning(false)
{
	// State constructor, initialize everything here
	g_defaultState = this;

	m_iconSet.addIcon(L"\uf2d3");
	m_iconSet.addIcon(L"\uf017");
	m_iconSet.addIcon(L"\uf250");
	m_iconSet.addIcon(L"\uf236");
	m_iconSet.setPosition(15.f, 13.f);
	m_iconSet.setSelectedIndex(m_mode);

	m_bottomView.setCenter(cpp3ds::Vector2f(160.f, 120.f));
	m_bottomView.setSize(cpp3ds::Vector2f(320.f, 240.f));

	//White screen used for transitions
	m_whiteScreen.setPosition(0.f, 30.f);
	m_whiteScreen.setSize(cpp3ds::Vector2f(320.f, 210.f));
	m_whiteScreen.setFillColor(cpp3ds::Color(255, 255, 255, 0));

	m_alarms.loadAlarms();
}

DefaultState::~DefaultState()
{
	m_alarms.saveAlarms();
}

void DefaultState::renderTopScreen(cpp3ds::Window& window)
{
	window.draw(m_topInfos);
	window.draw(m_clock);
	window.draw(m_calendar);
}

void DefaultState::renderBottomScreen(cpp3ds::Window& window)
{
	window.draw(m_iconSet);

	window.setView(m_bottomView);

	if (m_mode == Mode_Stopwatch)
		window.draw(m_stopwatch);
	else if (m_mode == Mode_Timer)
		window.draw(m_timer);
	else if (m_mode == Mode_Alarm)
		window.draw(m_alarms);

	window.setView(window.getDefaultView());

	if (m_isTransitioning)
		window.draw(m_whiteScreen);
}

bool DefaultState::update(float delta)
{
	// Always update the tween manager if you have one in your class
	m_tweenManager.update(delta);

	m_topInfos.update(delta);
	m_clock.update(delta);
	m_calendar.update(delta);

	m_iconSet.update(delta);

	// If selected icon changed, change mode accordingly
	int iconIndex = m_iconSet.getSelectedIndex();
	if (m_mode != iconIndex && iconIndex >= 0)
		setMode(static_cast<Mode>(iconIndex));

	if (m_mode == Mode_Stopwatch)
		m_stopwatch.update(delta);
	else if (m_mode == Mode_Timer)
		m_timer.update(delta);

	m_alarms.update(delta);

	return true;
}

bool DefaultState::processEvent(const cpp3ds::Event& event)
{
	m_calendar.processEvent(event);

	m_iconSet.processEvent(event);

	if (m_mode == Mode_Stopwatch)
		m_stopwatch.processEvent(event);
	else if (m_mode == Mode_Timer)
		m_timer.processEvent(event);
	else if (m_mode == Mode_Alarm)
		m_alarms.processEvent(event);

	return true;
}

void DefaultState::setMode(DefaultState::Mode mode)
{
	if (m_mode == mode || m_isTransitioning)
		return;

	TweenEngine::Tween::to(m_whiteScreen, m_whiteScreen.FILL_COLOR_ALPHA, 0.2f)
		.target(255.f)
		.setCallback(TweenEngine::TweenCallback::COMPLETE, [=](TweenEngine::BaseTween* source) {
			m_mode = mode;
		})
		.start(m_tweenManager);
	TweenEngine::Tween::to(m_whiteScreen, m_whiteScreen.FILL_COLOR_ALPHA, 0.2f)
		.target(0.f)
		.setCallback(TweenEngine::TweenCallback::COMPLETE, [=](TweenEngine::BaseTween* source) {
			m_isTransitioning = false;
		})
		.delay(0.4f)
		.start(m_tweenManager);

	if (mode > m_mode) {
		TweenEngine::Tween::to(m_bottomView, m_bottomView.CENTER_XY, 0.2f)
			.target(180.f, 120.f)
			.setCallback(TweenEngine::TweenCallback::COMPLETE, [=](TweenEngine::BaseTween* source) {
				m_bottomView.setCenter(cpp3ds::Vector2f(140.f, 120.f));
			})
			.start(m_tweenManager);
	} else {
		TweenEngine::Tween::to(m_bottomView, m_bottomView.CENTER_XY, 0.2f)
			.target(140.f, 120.f)
			.setCallback(TweenEngine::TweenCallback::COMPLETE, [=](TweenEngine::BaseTween* source) {
				m_bottomView.setCenter(cpp3ds::Vector2f(180.f, 120.f));
			})
			.start(m_tweenManager);
	}

	TweenEngine::Tween::to(m_bottomView, m_bottomView.CENTER_XY, 0.2f)
		.target(160.f, 120.f)
		.delay(0.4f)
		.start(m_tweenManager);

	m_isTransitioning = true;
}

} // namespace Clock
